// Copyright 2011 Google Inc. All Rights Reserved.

/**
 * @fileoverview This is the module used to store and upload test results.
 *
 * @author gavaletz@google.com (Eric Gavaletz)
 */


goog.provide('datastore');


goog.require('goog.Uri');
goog.require('goog.json');
goog.require('goog.net.XhrIo');


/**
 * The function to be called when the functionis set in the netscore.workList
 * is completed.
 *
 * @type {function()}
 */
datastore.nextFunction;


/**
 * An instance of goog.net.XhrIo for handling XMLHttpRequests.
 *
 * @type {goog.net.XhrIo}
 */
datastore.xhr = new goog.net.XhrIo();


/**
 * Storage for all the things we will want to send back to the server.
 *
 * @type {Object.<string, {*}>}
 */
datastore.json = {};


/**
 * Storage for errors.
 *
 * @type {Object.<string, string>}
 */
datastore.errors = {};


/**
 * The path to be used for uploading JS errors
 *
 * @type {string}
 */
datastore.errorPath = '/upload/JsError';


/**
 * Sets the error upload path.  Usually just used from the server.
 *
 * @param {string} s the path to be used.
 */
datastore.setErrorPath = function(s) {
  datastore.errorPath = s;
};
//used by the closure compiler to eport this function call
goog.exportProperty(window, 'datastoreSetErrorPath', datastore.setErrorPath);


/**
 * The path to be used for uploading data
 *
 * @type {string}
 */
datastore.path = '/upload';


/**
 * Sets the upload path.  Usually just used from the server.
 *
 * @param {string} s the path to be used.
 */
datastore.setPath = function(s) {
  datastore.path = s;
};
//used by the closure compiler to eport this function call
goog.exportProperty(window, 'datastoreSetPath', datastore.setPath);


/**
 * The key used for uploading and locating results.
 *
 * @type {string}
 */
datastore.resultKey = '';


/**
 * Sets the resultKey.  Usually just used from the server when loading archival
 * results.
 *
 * @param {string} s the result key to be used.
 */
datastore.setResultKey = function(s) {
  datastore.resultKey = s;
};
//used by the closure compiler to eport this function call
goog.exportProperty(window, 'datastoreSetResultKey', datastore.setResultKey);


/**
 * Sends all the data we have gathered to the server.
 */
datastore.postJson = function() {
  //make sure that we are setting the request time
  var requestTime = datastore.json['trackRequestTime'];
  if (typeof requestTime == 'undefined') {
    datastore.logError('trackRequestTime', 'undefined');
  }

  datastore.json['errors'] = datastore.errors;
  var data = goog.json.serialize(datastore.json);
  var postUri = new goog.Uri.parse();
  postUri.setPath(datastore.path);
  postUri.setParameterValue('gt', requestTime);
  datastore.xhr.send(postUri, 'POST', data,
      {'Content-Type': 'application/json'});
  datastore.resultKey = requestTime + '_' + datastore.json['trackRemoteAddr'];
  if (datastore.nextFunction) {
    datastore.nextFunction();
  }
};


/**
 * Callback for uploading the data.
 *
 * In some rare cases the server may not be able to store the data with the key
 * we gave it.  If this happens we need to update the key that we have and
 * maybe fix the things we did with it.
 *
 * @this {goog.net.XhrIo}
 * @param {goog.events.Event} e The event that triggered this call.
 */
datastore.postJsonDone = function(e) {
  if (datastore.resultKey != this.getResponseText()) {
    datastore.logError('datastore.resultKey',
        'mismatch with ' + this.getResponseText());
    //We might need to fix something if the missmatch breaks the URL
  }
};
//Register this function call with the uploader
goog.events.listen(datastore.xhr, goog.net.EventType.COMPLETE,
    datastore.postJsonDone);


/**
 * Lets the server know that the actual test is starting.
 */
datastore.updateRequestTime = function() {
  goog.net.XhrIo.send('/flock', datastore.updateRequestTimeDone);
};


/**
 * Callback for updating the request time.
 *
 * @this {goog.net.XhrIo}
 * @param {goog.events.Event} e The event that triggered this call.
 */
datastore.updateRequestTimeDone = function(e) {
  datastore.json['trackRequestTime'] = this.getResponseText();
};


/**
 * Method for logging errors locally and on the server.
 *
 * This method stores the error in the datastore by the key and sends it to the
 * server.
 *
 * @param {string} errKey the key for the error.
 * @param {string} errValue the message describing the error.
 */
datastore.logError = function(errKey, errValue) {
  datastore.errors[errKey] = errValue;
  var errUri = goog.Uri.parse(datastore.errorPath, false);
  errUri.setParameterValue('k', errKey);
  errUri.setParameterValue('v', errValue);
  goog.net.XhrIo.send(errUri);
};


/**
 * Dump all the datastore into a string and return it.
 *
 * @return {string} the serialized form of the datastore.
 */
datastore.debug = function() {
  return goog.json.serialize(datastore.json);
};
//used by the closure compiler to eport this function call
goog.exportProperty(window, 'datastoreDebug', datastore.debug);
